<template>
  <div class="page-view flex-column" @click="handleClickOutside">
    <div class="flex-between mb">
      <el-space size="large">
        <el-button type="primary" @click="resetFilters">Reset</el-button>
      </el-space>
      <slot name="btnContent"></slot>
    </div>

    <div style="flex: 1;overflow-y: auto;">
      <el-table v-loading="tableData.tableLoading" ref="myTableRef" class="jg-table" :data="tableData.data"
        style="width: 100%;height: 100%;" :border="Boolean(tableData.mergeKey)" :span-method="objectSpanMethod"
        @selection-change="handleSelectionChange" @row-click="rowClick" @sort-change="sortChange"
        @header-click="handleHeaderClick" :header-cell-class-name="handleHeadAddClass">

        <template v-for="(item, index) in  tableData.columnsData " :key="index">
          <!-- 多选 -->
          <el-table-column v-if="item.type === 'selection'" :type="item.type" :width="item.width" fixed />
          <!-- 单选 -->
          <el-table-column v-else-if="item.type === 'radio'" :width="item.width" fixed class-name="no-radio-label">
            <template #default="{ row, $index }">
              <el-radio @change="changeRadio" v-model="radioIndex" :label="$index"></el-radio>
            </template>
          </el-table-column>
          <!-- 渲染formatter -->
          <!-- <el-table-column v-else :property="item.field" :label="item.title" :width="item.width"
          :min-width="item.minWidth" :max-idth="item.maxWidth" :showOverflowTooltip="item.showOverflowTooltip"
          :sortable="item.sortable" :formatter="item.formatter" /> -->
          <el-table-column v-else :property="item.field" :label="item.title" :width="item.width"
            :min-width="item.minWidth" :max-idth="item.maxWidth" :showOverflowTooltip="item.showOverflowTooltip"
            :sortable="item.sortable" :formatter="item.formatter" :fixed="item.fixed">
            <template #header>
              <div class="table-header-div">
                <span class="title-span">{{ item.title }}</span>

                <!-- 控制筛选按钮显隐 -->
                <template v-if="item.field !== 'actionBtn' && item.formType">
                  <el-popover :visible="visible && item.field === showKey" :virtual-ref="refName" placement="bottom"
                    :width="'fit-content'">
                    <template #reference>

                      <!-- 两个筛选icon -->
                      <svg v-if="searchData[item.field] || searchData[item.field] === 0" :id="item.field"
                        @click.stop="toggleNameFilter(item.field, item)" t="1721807387166" class="icon icon-span"
                        viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5539" width="20"
                        height="20">
                        <path
                          d="M609.507556 463.246222H414.492444L170.666667 170.666667h682.666666l-243.825777 292.579555z m0 48.753778v212.878222L414.492444 853.333333V512h195.015112z"
                          fill="#11716f" p-id="5540"></path>
                      </svg>
                      <svg v-else :id="item.field" @click.stop="toggleNameFilter(item.field, item)" t="1721807387166"
                        class="icon icon-span" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
                        p-id="5539" width="20" height="20">
                        <path
                          d="M609.507556 463.246222H414.492444L170.666667 170.666667h682.666666l-243.825777 292.579555z m0 48.753778v212.878222L414.492444 853.333333V512h195.015112z"
                          fill="#c1c2c6" p-id="5540"></path>
                      </svg>
                      <!-- <el-icon class="icon-span" :id="item.field" @click.stop="toggleNameFilter(item.field, item)"
                        style="cursor: pointer; margin-left: 10px;"
                        :style="{ color: searchData[item.field] ? '#11716f' : '#85888e' }">
                        <Filter />
                      </el-icon> -->
                    </template>
                    <div>
                      <!-- 输入 -->
                      <el-input v-if="item.formType === 'input'" v-model="searchData[item.field]" :autofocus="true"
                        placeholder="请输入" @input="applyNameFilter" clearable style="margin-top: 10px; width: 150px;" />

                      <template v-if="!item.needGetList">
                        <!-- 下拉 -->
                        <el-select v-if="item.formType === 'select' || item.formType === 'radio'" filterable
                          :reserve-keyword="false" v-model="searchData[item.field]" placeholder="Please Select"
                          @change="applyTagFilter" clearable style="margin-top: 10px; width: 150px;">
                          <el-option v-for="item in item.selectList" :key="item" :value="item.value"
                            :label="item.name" />
                        </el-select>
                        <!-- 多选下拉 -->
                        <el-select v-if="item.formType === 'selectMultiple'" multiple filterable
                          :reserve-keyword="false" v-model="searchData[item.field]" placeholder="Please Select" clearable
                          style="margin-top: 10px; width: 150px;">
                          <el-option v-for="item in item.selectList" :key="item" :value="item.value"
                            :label="item.name" />
                        </el-select>
                      </template>
                      <!-- 多选下拉 需要搜索获取后端接口数据 -->
                      <el-select
                        v-if="(item.formType === 'select' || item.formType === 'selectMultiple') && item.needGetList"
                        multiple filterable remote :reserve-keyword="false" :loading="listLoading" remote-show-suffix
                        :remote-method="remoteMethod" v-model="searchData[item.field]" placeholder="请搜索后选择" clearable
                        style="margin-top: 10px; width: 150px;">
                        <el-option v-for="item in javaList" :key="item.value" :value="item.value" :label="item.name" />
                      </el-select>
                      <!-- 日期 && 日期时间 -->
                      <el-date-picker v-if="item.formType === 'daterange' || item.formType === 'datetimerange'"
                        style="width: 360px;" v-model="searchData[item.field]" :type="item.formType" range-separator="～"
                        start-placeholder="开始时间" end-placeholder="结束时间" :format="item.dateType"
                        @change="changeData($event, item.field, item.dateType)" />
                      <div class="mt" style="text-align: right;">
                        <el-button type="info" link @click="cancelFilter">重置</el-button>
                        <el-button type="primary" link @click="searchFilter">筛选</el-button>
                      </div>
                    </div>
                  </el-popover>
                </template>

              </div>
            </template>
          </el-table-column>
        </template>

      </el-table>
    </div>


    <pre>筛选和排序参数：{{ { ...searchData, ...sortJavaField } }}</pre>
    <!-- <pre>表格默认多列排序集合：{{ sortField }}</pre> -->
    <!-- <pre>表格参数：{{ tableData }}</pre> -->
  </div>
</template>

<script setup lang="jsx">
import { ref, defineOptions, defineEmits, defineProps, watch, } from 'vue' // 按需引入ref函数
import _ from 'lodash'
import moment from 'moment'
// import { getUserList } from '@/service/index.js'


defineOptions({
  name: "JgTable"
})

const emit = defineEmits(['setSearchData', 'updateHandleSelectionChange', 'updateChangeRadio', 'updateSortChange'])

const props = defineProps({
  description: {
    type: String,
    default: () => {
      return ' '
    }
  },
  tableDataObj: {
    type: Object,
    default: () => {
      return {}
    }
  },
})


let tableFlag = ref(false)//确保拿到父传子的表格数据再渲染
let tableData = ref({})
let myTableRef = ref(null) // 表格实例
let radioIndex = ref(null)

let searchData = ref({}) // 搜索参数 每个表头字段
// let sortObj = ref({}) // 单列排序
const sortField = ref({}) // 表格默认多列排序集合
const sortJavaField = ref({
  sortVOList: []
}) // 后端要的排序集合

// 时间格式化
const changeData = (value, key, dateType) => { 
  if (!_.isEmpty(value)) {
    searchData.value[key][0] = value[0] ? moment(value[0]).format(dateType) : ''
    searchData.value[key][1] = value[1] ? moment(value[1]).format(dateType) : ''
  } else {
    searchData.value[key] = []
  }
}

const showKey = ref(undefined) // 当前展示哪个筛选窗
const visible = ref(false) // 手动控制筛选窗显隐
const refName = ref(null) // 动态绑定在哪个表头图标下


// 全局重置
const resetFilters = () => {
  // searchData.value.nameFilter = {}
  for (const key in searchData.value) {
    if (Object.hasOwnProperty.call(searchData.value, key)) {
      searchData.value[key] = undefined
    }
  }
  visible.value = false

  sortField.value = {}
  sortJavaField.value.sortVOList = []
  // 因为无法通过element ui的api来清除排序样式，所以只能通过原生js来清除
  myTableRef.value.$el.querySelectorAll(".is-sortable").forEach((item) => {
    // 移除table表头中的排序样式descending和ascending
    item.classList.remove("descending");
    item.classList.remove("ascending");
  }) // 清除多个排序
  // myTableRef.value.clearSort() // 清除单个排序

  applyNameFilter()
  applyTagFilter()

  getData()
}

// 某些下拉数据 例如下拉大数据有500条 直接赋值会导致表格卡顿 通过点击表头再去接口获取数据赋值就不会影响表格的渲染
// （列里面数据回显使用后端给的中文，或者将javaList赋值给item的selectList）
let javaList = ref([])
const getJavaList = async (item) => {
  // 模拟几口
  await setTimeout(() => {
    item.selectList = Array.from({ length: 500 }).map((ele, index) => {
      return {
        name: index,
        value: index,
      }
    })
  }, 500);
}

const listLoading = ref(false)
// 远程搜索接口获取下拉数据
const remoteMethod = (query) => {
  if (query) {
    listLoading.value = true
    // getUserList({
    //   pageNum: 1,
    //   pageSize: 1000,
    //   chineseName: query
    // }).then((res = []) => {
    //   javaList.value = (res || []).map(ele => {
    //     return {
    //       name: ele.chineseName,
    //       value: ele.id,
    //     }
    //   })

    // }).finally(() => {
    //   listLoading.value = false
    // })

    // 模拟接口
    setTimeout(() => {
      javaList.value = Array.from({ length: 3 }).map((ele, index) => {
        return {
          name: '模拟' + index,
          value: index,
        }
      })
      listLoading.value = false
    }, 500);

  } else {
    // javaList.value = []
  }
}

// 触发筛选
const toggleNameFilter = async (key, item) => {
  // console.log(key, item);
  if (item.needJavaList) {
    await getJavaList(item) // 调用后端接口 获取下拉数据
  }

  if (visible.value && showKey.value && showKey.value !== key) {
    visible.value = false
    getData()
  }

  refName.value = document.getElementById(key)
  showKey.value = key
  visible.value = !visible.value
}

// 点击其他元素
const handleClickOutside = () => {
  // 且有筛选打开即去查询
  if (visible.value) {
    visible.value = false
    getData()
  }
};

// 重置
const cancelFilter = () => {
  searchData.value[showKey.value] = undefined
  visible.value = false;
  getData()
}
// 筛选
const searchFilter = () => {
  visible.value = false;
  getData()
}

// 单独过滤
const applyNameFilter = () => {
  // Filtering logic can be customized if needed
}
const applyTagFilter = () => {
  // Filtering logic can be customized if needed
}

const getData = () => {
  console.log('筛选参数', { ...searchData.value, ...sortJavaField.value });
  emit('setSearchData', { ...searchData.value, ...sortJavaField.value })
}


watch([() => props.tableDataObj, () => props.rulesData], ([tableDataObj, rulesData]) => {
  // console.log('监听');
  tableFlag.value = false
  tableData.value = _.cloneDeep(tableDataObj) // 使用lodash的深拷贝方法
  tableFlag.value = true

  // 判断空 也就是初次渲染时候需要排列出查询参数 后续数据变动不在初始化不在设置为undefined 否则会导致每次查询清空掉上次筛选条件
  if (_.isEmpty(searchData.value)) {
    tableDataObj?.columnsData.forEach(ele => {
      if (ele.field) {
        searchData.value[ele.field] = undefined
      }
    })
  }
}, { deep: true, immediate: true })

// 合并单元格
const objectSpanMethod = ({
  row,
  column,
  rowIndex,
}) => {
  // console.log(row, column, rowIndex, columnIndex,);
  const fields = tableData.value.mergeKey || []
  const cellValue = row[column.property]
  if (cellValue && fields.includes(column.property)) {
    const prevRow = tableData.value.data[rowIndex - 1]
    let nextRow = tableData.value.data[rowIndex + 1]
    if (prevRow && prevRow[column.property] === cellValue) {
      return { rowspan: 0, colspan: 0 }
    } else {
      let countRowspan = 1
      while (nextRow && nextRow[column.property] === cellValue) {
        nextRow = tableData.value.data[++countRowspan + rowIndex]
      }
      if (countRowspan > 1) {
        return { rowspan: countRowspan, colspan: 1 }
      }
    }
  }

}

// 多选
const handleSelectionChange = (val) => {
  // console.log(val);
  // 子传父
  emit('updateHandleSelectionChange', val);
}
// 单选
const changeRadio = (val) => {
  // console.log('单选', val, radioIndex.value.aa);
  let item = tableData.value.data?.[val] || {}
  emit('updateChangeRadio', item);
}

// 表格点击事件
const rowClick = (val) => {
  // console.log(val);
}


// 单列排序
// const sortChange = (val) => {
//   console.log(val, val.prop, val.order);
//   sortObj.value = {}
//   if (!_.isEmpty(val)) {
//     // sortObj.value[val.prop + 'Sort'] = val.order
//     sortObj.value['sortName'] = val.order
//     sortObj.value['sortType'] = val.prop
//   }
//   getData() // 直接统一在筛选里加入排序字段
//   // emit('updateSortChange', sortObj.value) // 不再单独传递排序字段
// }

// 多列排序
const sortChange = ({ order, prop }) => {
  visible.value = false
  //触发的排序和缓存的排序相同时，取消该字段的排序
  if (!order || sortField.value[prop] === order) {
    sortField.value[prop] = null;
  } else {
    sortField.value[prop] = order;
  }

  sortJavaField.value.sortVOList = []
  for (const key in sortField.value) {
    if (Object.hasOwnProperty.call(sortField.value, key)) {
      if (sortField.value[key]) {
        sortJavaField.value.sortVOList.push({
          sortName: key,
          sortType: sortField.value[key] === 'ascending' ? 'ASC' : sortField.value[key] === 'descending' ? 'DESC' : undefined,
        })
      }
    }
  }
  // console.log(sortField.value)
  getData() // 直接统一在筛选里加入排序字段
  // emit('updateSortChange', sortObj.value) // 不再单独传递排序字段
}
// 多列排序-类名样式保存
const handleHeadAddClass = ({ column }) => {
  if (sortField.value[column.property]) {
    column.order = sortField.value[column.property];
  }
}

// 表头点击事件
const handleHeaderClick = (column, event) => {
  // visible.value = false
  // console.log(column, event);
  // // 如果点击的是排序图标，不阻止事件，否则阻止默认的排序行为
  // const target = event.target
  // event.preventDefault();
  // event.stopPropagation();
  // event.cancelBubble = true
  // if (!target.classList.contains('caret-wrapper') && !target.classList.contains('ascending') && !target.classList.contains('descending')) {
  // }
}

</script>

<style lang="scss" lang="scss">
@import "./index.scss";
</style>

<style lang="scss" scoped>
:deep(.el-table) {
  thead {
    .cell {
      // background-color: #1fff;
      display: flex;
      min-width: 100px;
      position: relative;

      .table-header-div {
        // flex: 1;
        display: flex;

        .title-span {
          flex-grow: 1;
          word-break: break-word;
          /* 允许单词在任何地方断行 */
        }

        .el-only-child__content {
          height: 23px;
        }

        .icon-span {
          flex-shrink: 0;
          margin-top: 1px;
          margin-left: 5px;
          cursor: pointer;
          /* 防止缩小 */
          /* 给图标和标题之间添加一些间距 */
        }
      }

      .caret-wrapper {
        margin-top: 5px;
      }
    }
  }
}


// :deep(.el-table) {
//   thead {
//     .cell {

//       .table-header-div {
//         display: inline-block;

//         .title-span {
//         }
//       }

//       .caret-wrapper {
//         margin-top: -2px;
//       }
//     }
//   }
// }


// :deep(.el-table) {
//   thead {
//     .cell {
//       // display: flex;

//       .table-header-div {
//         // flex: 1;
//         display: flex;

//         .title-span {
//           // flex: 1;
//           white-space: nowrap!important;
//           text-overflow: ellipsis!important;
//           overflow: hidden!important;
//           word-break: break-all!important;
//         }

//         .icon-span {}
//       }

//       .caret-wrapper {
//         margin-top: 5px;

//       }
//     }
//   }
// }

// 去除单选框的内容
:deep(.no-radio-label) {
  .el-radio__label {
    display: none;
  }
}
</style>

